namespace cframework
{

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using UnityEngine;

    /// <summary>
    /// CSV列特性（支持自定义表头名，可用于类的属性或字段）
    /// </summary>
    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
    public class CsvColumnAttribute : Attribute
    {
        /// <summary>
        /// CSV表头显示名称（不设置则默认使用属性/字段名）
        /// </summary>
        public string ColumnName { get; }

        /// <summary>
        /// 是否忽略该属性/字段（默认不忽略）
        /// </summary>
        public bool Ignore { get; set; } = false;

        public CsvColumnAttribute(string columnName = null)
        {
            ColumnName = columnName;
        }
    }

    /// <summary>
    /// CSV序列化工具（支持属性和字段，处理特殊字符、中文编码）
    /// </summary>
    public static class CsvSerializer
    {
        /// <summary>
        /// 将对象列表序列化为CSV文本
        /// </summary>
        /// <typeparam name="T">对象类型（支持属性和字段）</typeparam>
        /// <param name="dataList">要序列化的数据列表</param>
        /// <param name="includeHeader">是否包含CSV表头</param>
        /// <param name="bindingFlags">字段/属性的访问权限（默认：公共实例成员）</param>
        /// <returns>CSV格式文本</returns>
        public static string SerializeToCsv<T>(List<T> dataList, bool includeHeader = true,
            BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance)
        {
            if (dataList == null || dataList.Count == 0)
            {
                Debug.LogWarning("序列化数据为空，返回空CSV");
                return string.Empty;
            }

            // 1. 获取类的可序列化成员（属性 + 字段）
            var serializableMembers = GetSerializableMembers<T>(bindingFlags);
            if (serializableMembers.Count == 0)
            {
                Debug.LogError("未找到可序列化的属性或字段");
                return string.Empty;
            }

            // 2. 构建StringBuilder拼接CSV内容
            var csvBuilder = new StringBuilder();

            // 3. 生成CSV表头（若需要）
            if (includeHeader)
            {
                var headerCells = serializableMembers.Select(member =>
                {
                    // 获取表头名（优先用CsvColumn特性，其次用成员名）
                    var columnAttr = member.GetCustomAttribute<CsvColumnAttribute>();
                    return EscapeCsvCell(columnAttr?.ColumnName ?? member.Name);
                });
                csvBuilder.AppendLine(string.Join(",", headerCells));
            }

            // 4. 生成CSV数据行（遍历每个对象的成员值）
            foreach (var data in dataList)
            {
                if (data == null) continue;

                var dataCells = serializableMembers.Select(member =>
                {
                    object value = null;
                    // 区分处理属性和字段
                    if (member is PropertyInfo property)
                    {
                        value = property.GetValue(data); // 获取属性值
                    }
                    else if (member is FieldInfo field)
                    {
                        value = field.GetValue(data); // 获取字段值
                    }

                    // 格式化值（处理null、bool、数值类型等）
                    string cellValue = FormatValue(value);
                    // 转义CSV特殊字符（逗号、引号、换行）
                    return EscapeCsvCell(cellValue);
                });

                csvBuilder.AppendLine(string.Join(",", dataCells));
            }

            return csvBuilder.ToString();
        }

        /// <summary>
        /// 从CSV文本反序列化为对象列表
        /// </summary>
        /// <typeparam name="T">目标对象类型（支持属性和字段）</typeparam>
        /// <param name="csvText">CSV格式文本</param>
        /// <param name="hasHeader">CSV是否包含表头</param>
        /// <param name="bindingFlags">字段/属性的访问权限（默认：公共实例成员）</param>
        /// <returns>反序列化后的对象列表</returns>
        public static List<T> DeserializeFromCsv<T>(string csvText, bool hasHeader = true,
            BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance) where T : new()
        {
            var resultList = new List<T>();
            if (string.IsNullOrEmpty(csvText))
            {
                Debug.LogWarning("反序列化的CSV文本为空");
                return resultList;
            }

            // 1. 按行分割CSV（处理Windows/Linux换行符）
            var csvLines = csvText.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
            if (csvLines.Length == 0)
            {
                Debug.LogWarning("CSV文本无有效数据行");
                return resultList;
            }

            // 2. 获取类的可序列化成员（属性 + 字段）
            var serializableMembers = GetSerializableMembers<T>(bindingFlags);
            if (serializableMembers.Count == 0)
            {
                Debug.LogError("未找到可序列化的属性或字段");
                return resultList;
            }

            // 3. 解析表头与成员的映射关系
            Dictionary<int, MemberInfo> columnMemberMap = new Dictionary<int, MemberInfo>();
            int startLineIndex = 0; // 数据行起始索引（有表头则从1开始）

            if (hasHeader)
            {
                // 解析表头行，建立“列索引→成员”的映射
                var headerCells = ParseCsvLine(csvLines[0]);
                for (int i = 0; i < headerCells.Count; i++)
                {
                    string headerName = headerCells[i].Trim();
                    // 匹配成员（优先按CsvColumn特性的ColumnName，其次按成员名）
                    var matchedMember = serializableMembers.FirstOrDefault(member =>
                    {
                        var columnAttr = member.GetCustomAttribute<CsvColumnAttribute>();
                        string memberHeaderName = columnAttr?.ColumnName ?? member.Name;
                        return string.Equals(memberHeaderName, headerName, StringComparison.OrdinalIgnoreCase);
                    });

                    if (matchedMember != null)
                    {
                        columnMemberMap.Add(i, matchedMember);
                    }
                    else
                    {
                        Debug.LogWarning($"CSV表头“{headerName}”未找到对应的属性/字段，将忽略该列");
                    }
                }
                startLineIndex = 1; // 跳过表头行
            }
            else
            {
                // 无表头：按成员顺序直接映射（列索引0→第一个成员，以此类推）
                for (int i = 0; i < serializableMembers.Count && i < csvLines[0].Split(',').Length; i++)
                {
                    columnMemberMap.Add(i, serializableMembers[i]);
                }
            }

            // 4. 解析数据行，赋值到对象
            for (int lineIdx = startLineIndex; lineIdx < csvLines.Length; lineIdx++)
            {
                string line = csvLines[lineIdx];
                if (string.IsNullOrWhiteSpace(line)) continue;

                // 解析当前行的单元格（处理引号包裹的特殊内容）
                var dataCells = ParseCsvLine(line);
                // 创建目标对象实例
                T dataObj = new T();

                // 遍历列映射，给对象的属性/字段赋值
                foreach (var (columnIdx, member) in columnMemberMap)
                {
                    // 确保列索引不超出当前行的单元格数量
                    if (columnIdx >= dataCells.Count)
                    {
                        Debug.LogWarning($"第{lineIdx + 1}行：列索引{columnIdx}超出单元格数量，跳过赋值");
                        continue;
                    }

                    string cellValue = dataCells[columnIdx].Trim();
                    try
                    {
                        // 根据成员类型（属性/字段）获取目标类型
                        Type targetType = member is PropertyInfo property
                            ? property.PropertyType
                            : (member as FieldInfo).FieldType;

                        // 转换单元格值为目标类型
                        object value = ConvertValue(cellValue, targetType);

                        // 给属性/字段赋值
                        if (member is PropertyInfo prop)
                        {
                            prop.SetValue(dataObj, value);
                        }
                        else if (member is FieldInfo field)
                        {
                            field.SetValue(dataObj, value);
                        }
                    }
                    catch (Exception e)
                    {
                        Debug.LogError($"第{lineIdx + 1}行列{columnIdx}赋值失败：{e.Message}");
                        continue;
                    }
                }

                resultList.Add(dataObj);
            }

            return resultList;
        }

        /// <summary>
        /// 保存CSV文本到本地文件（自动创建目录，UTF-8编码）
        /// </summary>
        public static bool SaveCsvToFile(string csvText, string filePath)
        {
            try
            {
                // 创建目录（若不存在）
                string directory = Path.GetDirectoryName(filePath);
                if (!Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                }

                // 写入文件（UTF-8编码，避免中文乱码）
                File.WriteAllText(filePath, csvText, Encoding.UTF8);
                Debug.Log($"CSV文件保存成功：{filePath}");
                return true;
            }
            catch (Exception e)
            {
                Debug.LogError($"CSV文件保存失败：{e.Message}");
                return false;
            }
        }

        /// <summary>
        /// 从本地文件读取CSV文本（UTF-8编码）
        /// </summary>
        public static string LoadCsvFromFile(string filePath)
        {
            try
            {
                if (!File.Exists(filePath))
                {
                    Debug.LogError($"CSV文件不存在：{filePath}");
                    return string.Empty;
                }

                // 读取文件（UTF-8编码）
                string csvText = File.ReadAllText(filePath, Encoding.UTF8);
                Debug.Log($"CSV文件读取成功：{filePath}（长度：{csvText.Length}字符）");
                return csvText;
            }
            catch (Exception e)
            {
                Debug.LogError($"CSV文件读取失败：{e.Message}");
                return string.Empty;
            }
        }

        #region 内部辅助方法
        /// <summary>
        /// 获取类的可序列化成员（属性 + 字段，排除Ignore=true的成员）
        /// </summary>
        private static List<MemberInfo> GetSerializableMembers<T>(BindingFlags bindingFlags)
        {
            Type type = typeof(T);
            // 获取所有符合条件的属性（排除索引器、忽略标记为Ignore的）
            var properties = type.GetProperties(bindingFlags)
                .Where(prop => !prop.GetIndexParameters().Any()) // 排除索引器（如List的this[]）
                .Where(prop =>
                {
                    var attr = prop.GetCustomAttribute<CsvColumnAttribute>();
                    return attr == null || !attr.Ignore;
                })
                .Cast<MemberInfo>();

            // 获取所有符合条件的字段（排除忽略标记为Ignore的）
            var fields = type.GetFields(bindingFlags)
                .Where(field =>
                {
                    var attr = field.GetCustomAttribute<CsvColumnAttribute>();
                    return attr == null || !attr.Ignore;
                })
                .Cast<MemberInfo>();

            // 合并属性和字段，按成员名排序（确保顺序一致）
            return properties.Concat(fields)
                .OrderBy(member => member.Name)
                .ToList();
        }

        /// <summary>
        /// 格式化值为字符串（处理null、bool、数值类型）
        /// </summary>
        private static string FormatValue(object value)
        {
            if (value == null) return string.Empty;

            Type valueType = value.GetType();
            // 处理bool类型（统一转为"True"/"False"，便于反序列化）
            if (valueType == typeof(bool))
            {
                return ((bool)value).ToString();
            }
            // 处理数值类型（保留原始格式，避免科学计数法）
            if (valueType.IsNumericType())
            {
                return value.ToString();
            }
            // 其他类型直接转字符串
            return value.ToString();
        }

        /// <summary>
        /// 转换字符串为目标类型（支持可空类型、基础类型）
        /// </summary>
        private static object ConvertValue(string cellValue, Type targetType)
        {
            // 处理空字符串（值类型返回默认值，引用类型返回null）
            if (string.IsNullOrEmpty(cellValue))
            {
                return targetType.IsValueType ? Activator.CreateInstance(targetType) : null;
            }

            // 处理可空类型（如int?、bool?）
            Type underlyingType = Nullable.GetUnderlyingType(targetType);
            if (underlyingType != null)
            {
                return Convert.ChangeType(cellValue, underlyingType);
            }

            // 处理基础类型转换
            return Convert.ChangeType(cellValue, targetType);
        }

        /// <summary>
        /// 转义CSV单元格特殊字符（逗号、引号、换行）
        /// 规则：包含特殊字符则用双引号包裹，内部双引号替换为两个双引号
        /// </summary>
        private static string EscapeCsvCell(string cellValue)
        {
            if (string.IsNullOrEmpty(cellValue))
            {
                return string.Empty;
            }

            // 判断是否需要转义（包含逗号、双引号、换行符）
            bool needEscape = cellValue.Contains(',') || cellValue.Contains('"') ||
                             cellValue.Contains('\r') || cellValue.Contains('\n');

            if (!needEscape)
            {
                return cellValue;
            }

            // 转义规则：用双引号包裹，内部双引号替换为两个双引号
            string escapedValue = cellValue.Replace("\"", "\"\"");
            return $"\"{escapedValue}\"";
        }

        /// <summary>
        /// 解析CSV行（处理引号包裹的单元格，支持包含逗号、换行的单元格）
        /// </summary>
        private static List<string> ParseCsvLine(string line)
        {
            var cells = new List<string>();
            var currentCell = new StringBuilder();
            bool inQuotes = false; // 是否处于引号包裹状态

            foreach (char c in line)
            {
                if (c == '"')
                {
                    if (inQuotes)
                    {
                        // 处于引号内：判断下一个字符是否也是引号（双引号转义）
                        int nextIndex = line.IndexOf(c, currentCell.Length + 1);
                        if (nextIndex == currentCell.Length + 1)
                        {
                            // 下一个字符是引号，添加一个引号到当前单元格，跳过下一个字符
                            currentCell.Append('"');
                            continue; // 跳过下一个引号（因为当前循环会处理完当前c，下一轮会处理下一个c，这里需调整索引？）
                        }
                        else
                        {
                            // 引号结束，退出引号状态
                            inQuotes = false;
                        }
                    }
                    else
                    {
                        // 进入引号状态
                        inQuotes = true;
                    }
                }
                else if (c == ',' && !inQuotes)
                {
                    // 逗号且不在引号内：单元格结束
                    cells.Add(currentCell.ToString());
                    currentCell.Clear();
                }
                else
                {
                    // 普通字符，添加到当前单元格
                    currentCell.Append(c);
                }
            }

            // 添加最后一个单元格
            cells.Add(currentCell.ToString());
            return cells;
        }

        /// <summary>
        /// 扩展方法：判断类型是否为数值类型（包含int、float、double等）
        /// </summary>
        private static bool IsNumericType(this Type type)
        {
            if (type == null) return false;

            TypeCode typeCode = Type.GetTypeCode(type);
            return typeCode >= TypeCode.SByte && typeCode <= TypeCode.Decimal;
        }
        #endregion
    }
}